feat(cli): tell CLI/TUI when a newer release is available (#60) - #61
Conversation
Android 早就有 UpdateChecker,Linux/CLI/TUI 一直没有「有新版」提示, 这里把同一套做法移植过来:不加依赖、不开新端口。 - 启动时异步查一次 GitHub latest release,有新版最多多打一行 update: 日志; TUI 里按 u 可手动重查。 - 任何失败(离线、被挡、403/429/5xx、返回体不可解析)都静默忽略, 从不抛异常、不阻塞启动;10s 超时用的定时器 unref,不吊住进程。 - ZCODE_UPDATE_CHECK=off 关闭检查;ZCODE_UPDATE_SKIP=v4.7.6 忽略某个版本。 - 容器内提示 docker compose pull && docker compose up -d(镜像不可变, release 也还没有校验和),不做自动下载替换。 - 手动检查不受环境变量与忽略列表影响,且一定给答复(已是最新 / 不可用)。 测试:src/update/check.test.ts 24 个用例(注入 fetch、不发网络请求); bun x tsc --noEmit 通过;全量 bun test 969 通过(另有 Windows 既有的 captcha worker 用例失败,master 上同样失败)。 Refs TriDefender#60 Signed-off-by: Ma6302 <143102004+Ma6302@users.noreply.github.com>
TriDefender
left a comment
There was a problem hiding this comment.
结合 issue #60 审查。启动异步检查、静默失败、环境变量开关、手动入口和不自动替换的总体方向符合需求。请修正下面几处行为问题后再合并。没有在本次审查中复跑测试。
| // ZCODE_UPDATE_CHECK=off and the muted-tag list, and always answers visibly. | ||
| let updateCheckInFlight = false; | ||
| async function runUpdateCheck(manual = false): Promise<void> { | ||
| if (updateCheckInFlight) return; |
There was a problem hiding this comment.
[P2] 启动自动检查还在进行时按 u 会静默失效。runTui 启动时已调用 runUpdateCheck(),这里会直接丢弃随后的手动请求;若启动检查最后是 up-to-date、skipped 或 unavailable,用户按 u 不会收到结果,也无法通过手动检查绕过 skip/关闭设置。请排队执行手动检查,或确保当前请求完成后再给出手动检查结果。
|
|
||
| /** `v4.7.6-android` → `4.7.6`; `""` when there is no numeric core. */ | ||
| function versionCore(tag: string): string { | ||
| const match = /^v?(\d+(?:\.\d+){0,2})/.exec(tag.trim()); |
There was a problem hiding this comment.
[P2] 这个正则只匹配 tag 开头,没有校验数字版本后的边界。比如 v4.7.6garbage 会解析成 4.7.6,当当前版本是 4.7.5 时仍会持续报告有更新,与 PR 所述“非 plain version 不提示”不符。请只接受完整版本或明确允许的后缀形式,并覆盖这种畸形 tag。
| } | ||
|
|
||
| export function updateCommand(release: ReleaseInfo, inContainer: boolean): string { | ||
| return inContainer ? "docker compose pull && docker compose up -d" : `re-download from ${release.url}`; |
There was a problem hiding this comment.
[P3] isContainerRuntime 也会识别 Podman(/.containerenv),但这里始终输出 docker compose ...。Podman-only 主机收到的更新指令可能无法执行。请根据运行时生成对应命令,或改成不假定 Docker Compose 的通用容器更新提示。
- 版本 tag 只接受完整版本或明确分隔的变体后缀(v4.7.5 / 4.8 / v4.7.2.android / v4.5.4-AppOverhaul / v4.7.6-rc.1)。此前 `v4.7.6garbage`、`v4.7.6.1` 会被截成 4.7.6,导致当前版本 4.7.5 时永久提示有新版;现在这类 tag 没有版本核心, 一律不判为更新(补充畸形 tag 用例)。 - 容器提示按检测到的运行时生成,不再假定 Docker:Docker → docker compose pull && docker compose up -d;Podman(/.containerenv 或 container=podman)→ podman compose pull && podman compose up -d;识别不出的容器(如 container=lxc)→ 不假定 compose 的 通用提示「pull the new image and recreate the container」。isContainerRuntime 保留为 detectContainerRuntime 的兼容包装。 - TUI:启动时的自动检查还在进行中按 u 不再被静默丢弃。新增 createUpdateCheckQueue 单飞调度:自动检查重复调用直接丢弃,手动检查排队并在当前请求结束后用 force 重跑 (启动那次可能是 up-to-date / skipped / unavailable,或被 ZCODE_UPDATE_CHECK=off 关掉,不能当作手动请求的答复),重复按 u 合并为一次。 - README / README_EN 同步说明容器提示与运行时有关。 Refs TriDefender#60 Signed-off-by: Ma6302 <143102004+Ma6302@users.noreply.github.com>
|
谢谢审查。三处都改了,第二提交 1. 已改为排队。新增 这里确实不能把启动那次的结果当手动答复:它可能是 2. 版本 tag 改为严格语法,数字版本后必须是字符串结尾或明确分隔符 + 字母开头的后缀: const VERSION_TAG = /^v?(\d+(?:\.\d+){0,2})(?:[.-][A-Za-z][0-9A-Za-z.-]*)?$/;于是 3. 新增
验证(第二个提交
README / README_EN 里对应的段落也同步改了(容器提示与检测到的运行时有关)。 |
|
LGTM |
Refs #60 — notify-only scope.
What
Android already ships an
UpdateChecker; the Linux / CLI / TUI side had no way to learn that a newer release exists. This ports the same behaviour, with no new dependency and no new port:src/update/check.tsasks the GitHub latest release endpoint once, asynchronously at startup.serveprints at most one extraupdate:line when a newer release exists; the TUI prints the same line and adds u for a manual re-check.ZCODE_UPDATE_CHECK=offdisables the check;ZCODE_UPDATE_SKIP=v4.7.6mutes a single tag.docker compose pull && docker compose up -d(the image is immutable) — nothing is downloaded or replaced in place.Behaviour contract (same as the Android checker)
tag_nameis not a plain version all end in "no notice".AbortControllertimeout whose timer isunref'd, so it cannot hold the process open.4.7.10>4.7.9); an unparsable tag is never reported as newer. Suffixed tags such asv4.7.2.androidcompare on the numeric core.User-Agent(GitHub returns 403 without one) andAccept: application/vnd.github+json.Why notify and not self-update
Release artifacts carry no checksum file, so a downloaded binary cannot be verified before replacing a running one; and inside Docker the image is immutable anyway. Android only notifies today, so this keeps one behaviour across platforms.
Tests
src/update/check.test.ts: 24 cases, all with an injected fetch (no network), covering version comparison, env/skip handling, container detection, notice text, response parsing and 8 failure modes.bun x tsc --noEmitclean; fullbun test969 pass, plus the pre-existing Windows-only captcha-worker failure (an unloadable worker entry degrades to in-process solving) that also fails on master.4.7.4→ notice forv4.7.5;4.7.5→ up to date;ZCODE_UPDATE_CHECK=off→ unavailable.Docs
README.md/README_EN.md: two environment rows plus an "update notice" paragraph.Out of scope
Automatic download/replace, a checksum file, and a way to skip a version other than the env var. Happy to follow up on any of them.